package com.link2room.optimus.facade.impl;

import com.link2room.common.util.DateUtil;
import com.link2room.common.util.L2RAssert;
import com.link2room.ironhide.dto.param.base.RoomtypeBaseParamDto;
import com.link2room.ironhide.dto.result.base.L2RRoomtypeDto;
import com.link2room.optimus.dto.param.base.PriceStaticBaseParamDto;
import com.link2room.common.entity.BaseEntity;
import com.link2room.common.jpa.condition.ConditionDetail;
import com.link2room.common.jpa.condition.L2RCondition;
import com.link2room.common.jpa.criteria.CriteriaUtil;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.ClassConverUtil;
import com.link2room.common.util.StringUtil;
import com.link2room.optimus.entity.PriceStatic;
import com.link2room.optimus.entity.PriceStaticDay;
import com.link2room.optimus.entity.PriceStaticWeek;
import com.link2room.optimus.dto.result.base.PriceDto;
import com.link2room.optimus.dto.result.base.PriceStaticDayDto;
import com.link2room.optimus.dto.result.base.PriceStaticDto;
import com.link2room.optimus.dto.result.base.PriceStaticWeekDto;
import com.link2room.optimus.facade.IStaticPriceFacadeService;
import com.link2room.optimus.feign.ironhide.RoomtypeFeignService;
import com.link2room.optimus.mapper.PriceStaticMapper;
import com.link2room.optimus.service.IMarketingService;
import com.link2room.optimus.service.IStaticPriceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by sss on 2016/8/26.
 */
@Component("staticPriceFacadeService")
public class StaticPriceFacadeServiceImpl implements IStaticPriceFacadeService {
    @Resource
    private ICommonService commonService;
    @Resource
    private IStaticPriceService staticPriceService;
    @Autowired
    private RoomtypeFeignService roomtypeFeignService;
    @Resource
    private IMarketingService marketingService;


    /**
     * 保存价格设置
     * @param basePriceStaticBaseParamDto
     * @throws Exception
     */
    @Override
    public PriceDto saveOrUpdateStaticPrice(PriceStaticBaseParamDto basePriceStaticBaseParamDto) throws Exception {
        //全局价
        List<PriceStatic> priceStaticList=null;
        if(basePriceStaticBaseParamDto.getStaticPrices()!=null&& basePriceStaticBaseParamDto.getStaticPrices().size()>0){
            priceStaticList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getStaticPrices(),PriceStatic.class);
        }
        //星期价
        List<PriceStaticWeek> priceStaticWeekList=null;
        if(basePriceStaticBaseParamDto.getWeekPrices()!=null&& basePriceStaticBaseParamDto.getWeekPrices().size()>0){
            priceStaticWeekList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getWeekPrices(),PriceStaticWeek.class);
        }
        //特殊日期价
        List<PriceStaticDay> priceStaticDayList=null;
        if(basePriceStaticBaseParamDto.getDayPrices()!=null&& basePriceStaticBaseParamDto.getDayPrices().size()>0){
           priceStaticDayList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getDayPrices(),PriceStaticDay.class);
        }

        staticPriceService.saveOrUpdateBasePrice(basePriceStaticBaseParamDto.getLhotelGroupCode(), basePriceStaticBaseParamDto.getLhotelCode(), basePriceStaticBaseParamDto.getRmtype() ,
                basePriceStaticBaseParamDto.getPriceCode(),priceStaticList, priceStaticWeekList, priceStaticDayList);
        PriceDto priceDto=new PriceDto();
        priceDto.setStaticPrices(ClassConverUtil.copyPropertiesList(priceStaticList,PriceStaticDto.class));
        priceDto.setWeekPrices(ClassConverUtil.copyPropertiesList(priceStaticWeekList,PriceStaticWeekDto.class));
        priceDto.setDayPrices(ClassConverUtil.copyPropertiesList(priceStaticDayList,PriceStaticDayDto.class));
        return priceDto;
    }

    /**
     * 保存每日价格设置
     * @param basePriceStaticBaseParamDto
     * @throws Exception
     */
    @Override
    public PriceStaticDayDto saveOrUpdateStaticPriceDay(PriceStaticBaseParamDto basePriceStaticBaseParamDto) throws Exception {
        if(basePriceStaticBaseParamDto.getDayPrice()!=null){
            PriceStaticDay priceStaticDay=ClassConverUtil.copyProperties(basePriceStaticBaseParamDto.getDayPrice(),PriceStaticDay.class);
            commonService.saveOrUpdate(priceStaticDay);
            return ClassConverUtil.copyPropertiesToDto(priceStaticDay,PriceStaticDayDto.class,false);
        }else {
            return null;
        }

    }

    /**
     * 保存批量每日价格设置
     * @param basePriceStaticBaseParamDto
     * @return
     * @throws Exception
     */
    @Override
    public List<PriceStaticDayDto> saveOrUpdateStaticPriceDayList(PriceStaticBaseParamDto basePriceStaticBaseParamDto) throws Exception {
        //特殊日期价
        if(basePriceStaticBaseParamDto.getDayPrices()!=null&& basePriceStaticBaseParamDto.getDayPrices().size()>0){
            List<PriceStaticDay> priceStaticDayList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getDayPrices(),PriceStaticDay.class);
            commonService.saveOrUpdateList(priceStaticDayList);
            return ClassConverUtil.copyPropertiesListToDtoList(priceStaticDayList,PriceStaticDayDto.class,false);
        }else {
            return null;
        }

    }

    /**
     * 保存价格设置
     * @param basePriceStaticBaseParamDto
     * @throws Exception
     */
    @Override
    public PriceDto dealStaticPrice(PriceStaticBaseParamDto basePriceStaticBaseParamDto) throws Exception {
        //全局价
        List<PriceStatic> priceStaticList=null;
        if(basePriceStaticBaseParamDto.getStaticPrices()!=null&& basePriceStaticBaseParamDto.getStaticPrices().size()>0){
            priceStaticList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getStaticPrices(),PriceStatic.class);
        }
        //星期价
        List<PriceStaticWeek> priceStaticWeekList=null;
        if(basePriceStaticBaseParamDto.getWeekPrices()!=null&& basePriceStaticBaseParamDto.getWeekPrices().size()>0){
            priceStaticWeekList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getWeekPrices(),PriceStaticWeek.class);
        }
        List<Long> delWeekPriceList=new ArrayList<>();
        if(priceStaticWeekList!=null){
            Iterator<PriceStaticWeek> weekIterator = priceStaticWeekList.iterator();
            while (weekIterator.hasNext()){
                PriceStaticWeek weekPrice = weekIterator.next();
                if(weekPrice.getPrice()==null){
                    weekIterator.remove();
                    if(weekPrice.getId()!=null){
                        delWeekPriceList.add(weekPrice.getId());
                    }
                }
            }
        }
        //特殊日期价
        List<PriceStaticDay> priceStaticDayList=null;
        if(basePriceStaticBaseParamDto.getDayPrices()!=null&& basePriceStaticBaseParamDto.getDayPrices().size()>0){
            priceStaticDayList=ClassConverUtil.copyPropertiesList(basePriceStaticBaseParamDto.getDayPrices(),PriceStaticDay.class);
        }
        List<Long> delDayPriceList=new ArrayList<>();
        if(priceStaticDayList!=null){
            Iterator<PriceStaticDay> dayIterator = priceStaticDayList.iterator();
            while (dayIterator.hasNext()){
                PriceStaticDay dayPrice = dayIterator.next();
                if(dayPrice.getPrice()==null) {
                    dayIterator.remove();
                    if (dayPrice.getId() != null) {
                        delDayPriceList.add(dayPrice.getId());
                    }
                }
            }
        }
        staticPriceService.dealBasePrice(priceStaticList, priceStaticWeekList, priceStaticDayList,delWeekPriceList.toArray(),delDayPriceList.toArray());
        PriceDto priceDto=new PriceDto();
        priceDto.setStaticPrices(ClassConverUtil.copyPropertiesList(priceStaticList,PriceStaticDto.class));
        priceDto.setWeekPrices(ClassConverUtil.copyPropertiesList(priceStaticWeekList,PriceStaticWeekDto.class));
        priceDto.setDayPrices(ClassConverUtil.copyPropertiesList(priceStaticDayList,PriceStaticDayDto.class));
        return priceDto;
    }

    /**
     * 列出酒店房型价格设置
     * @param priceStaticBaseParamDto
     * @return
     * @throws Exception
     */
    @Override
    public List<PriceDto> listPriceStaticDto(PriceStaticBaseParamDto priceStaticBaseParamDto)throws Exception{
        List<String> rmtypeList=new ArrayList<>();
        if(StringUtil.isNotBlank(priceStaticBaseParamDto.getRmtype())){
            rmtypeList.add(priceStaticBaseParamDto.getRmtype());
        }else {
            RoomtypeBaseParamDto roomtypeBaseParamDto =new RoomtypeBaseParamDto();
            roomtypeBaseParamDto.setLhotelGroupCode(priceStaticBaseParamDto.getLhotelGroupCode());
            roomtypeBaseParamDto.setLhotelCode(priceStaticBaseParamDto.getLhotelCode());
            QueryResult<L2RRoomtypeDto> roomtypeQueryResult = roomtypeFeignService.listRoomtype(roomtypeBaseParamDto.paramToMap()).getQueryResult();
            if(roomtypeQueryResult.getResultlist()!=null&&roomtypeQueryResult.getResultlist().size()>0){
                for(L2RRoomtypeDto l2RRoomtypeDto :roomtypeQueryResult.getResultlist()){
                    rmtypeList.add(l2RRoomtypeDto.getRmtype());
                }
            }
        }

        PriceStatic queryPriceStatic=new PriceStatic();
        queryPriceStatic.setLhotelGroupCode(priceStaticBaseParamDto.getLhotelGroupCode());
        queryPriceStatic.setLhotelCode(priceStaticBaseParamDto.getLhotelCode());
        queryPriceStatic.setPriceCode(priceStaticBaseParamDto.getPriceCode());
        if(StringUtil.isNotBlank(priceStaticBaseParamDto.getRmtype())){
            queryPriceStatic.setRmtype(priceStaticBaseParamDto.getRmtype());
        }
        QueryResult<PriceStatic> priceStaticResult = commonService.findAllEQ(PriceStatic.class, queryPriceStatic);

        PriceStaticWeek queryPriceStaticWeek=new PriceStaticWeek();
        queryPriceStaticWeek.setLhotelGroupCode(priceStaticBaseParamDto.getLhotelGroupCode());
        queryPriceStaticWeek.setLhotelCode(priceStaticBaseParamDto.getLhotelCode());
        queryPriceStaticWeek.setPriceCode(priceStaticBaseParamDto.getPriceCode());
        if(StringUtil.isNotBlank(priceStaticBaseParamDto.getRmtype())){
            queryPriceStaticWeek.setRmtype(priceStaticBaseParamDto.getRmtype());
        }
        QueryResult<PriceStaticWeek> priceStaticWeekResult = commonService.findAllEQ(PriceStaticWeek.class, queryPriceStaticWeek);

        List<PriceStaticDayDto> dayPriceList=null;
        if(priceStaticBaseParamDto.getStartDate()!=null&&priceStaticBaseParamDto.getEndDate()!=null){
            L2RCondition l2RCondition=new L2RCondition();
            l2RCondition.setAndConditions(new ConditionDetail[]{
                    new ConditionDetail(BaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, priceStaticBaseParamDto.getLhotelGroupCode()),
                    new ConditionDetail(BaseEntity.BaseEntity_.lhotelCode.toString(), CriteriaUtil.Operator.EQ, priceStaticBaseParamDto.getLhotelCode()),
                    new ConditionDetail(PriceStaticDay.PriceStaticDay_.priceCode.toString(), CriteriaUtil.Operator.EQ, priceStaticBaseParamDto.getPriceCode()),
                    new ConditionDetail(PriceStaticDay.PriceStaticDay_.rmtype.toString(), CriteriaUtil.Operator.EQ, priceStaticBaseParamDto.getRmtype()),
                    new ConditionDetail(PriceStaticDay.PriceStaticDay_.priceDate.toString(), CriteriaUtil.Operator.GTE, priceStaticBaseParamDto.getStartDate()),
                    new ConditionDetail(PriceStaticDay.PriceStaticDay_.priceDate.toString(), CriteriaUtil.Operator.LTE, priceStaticBaseParamDto.getEndDate()),
            });
            QueryResult<PriceStaticDay> priceStaticDayResult = commonService.findAllByCondition(PriceStaticDay.class,l2RCondition);
            dayPriceList = ClassConverUtil.copyPropertiesListToDtoList(priceStaticDayResult.getResultlist(), PriceStaticDayDto.class, false);
        }

        List<PriceStaticDto> basePriceList = ClassConverUtil.copyPropertiesListToDtoList(priceStaticResult.getResultlist(), PriceStaticDto.class, false);
        List<PriceStaticWeekDto> weekPriceList = ClassConverUtil.copyPropertiesListToDtoList(priceStaticWeekResult.getResultlist(), PriceStaticWeekDto.class, false);
       List<PriceDto> priceList=new ArrayList<>();
       for(String rmtype:rmtypeList){
           PriceDto priceDto=new PriceDto();
           priceDto.setRmtype(rmtype);
           priceDto.setLhotelGroupCode(priceStaticBaseParamDto.getLhotelGroupCode());
           priceDto.setLhotelCode(priceStaticBaseParamDto.getLhotelCode());
           List<PriceStaticDto> priceStaticList=new ArrayList<>();
           List<PriceStaticWeekDto> priceStaticWeekList=new ArrayList<>();
           List<PriceStaticDayDto> priceStaticDayList=new ArrayList<>();
           for(PriceStaticDto basePrice:basePriceList){
               if(rmtype.equals(basePrice.getRmtype())){
                   priceStaticList.add(basePrice);
               }
           }
           if(weekPriceList!=null){
               for(PriceStaticWeekDto weekPrice:weekPriceList){
                   if(rmtype.equals(weekPrice.getRmtype())){
                       priceStaticWeekList.add(weekPrice);
                   }
               }
           }
           if(dayPriceList!=null){
               for(PriceStaticDayDto dayPrice:dayPriceList){
                   if(rmtype.equals(dayPrice.getRmtype())){
                       priceStaticDayList.add(dayPrice);
                   }
               }
           }
           priceDto.setStaticPrices(priceStaticList);
           priceDto.setWeekPrices(priceStaticWeekList);
           priceDto.setDayPrices(priceStaticDayList);
           priceList.add(priceDto);
       }
        return priceList;
    }

    /**
     * 列出每日价格
     * @param priceStaticBaseParamDto
     * @return
     * @throws Exception
     */
    @Override
    public QueryResult<PriceStaticDayDto> listPriceStaticDays(PriceStaticBaseParamDto priceStaticBaseParamDto)throws Exception {
        QueryResult<PriceStaticMapper> priceStaticMapperQueryResult = marketingService.getRmtypeStaticPrice(priceStaticBaseParamDto.getLhotelGroupCode(),
                priceStaticBaseParamDto.getLhotelCode(),
                priceStaticBaseParamDto.getPriceCode(),
                priceStaticBaseParamDto.getRmtype(),
                priceStaticBaseParamDto.getStartDatetime(),
                DateUtil.getWebDateString(DateUtil.addDays(priceStaticBaseParamDto.getEndDate(), 1L))
        );
       List<PriceStaticDayDto> priceStaticDayDtoList=Optional.ofNullable(priceStaticMapperQueryResult.getResultlist()).map(value->value.stream().map(priceStaticMapper->{
            PriceStaticDayDto priceStaticDayDto=ClassConverUtil.copyProperties(priceStaticMapper,PriceStaticDayDto.class);
            priceStaticDayDto.setPriceDate(priceStaticMapper.getDate());
            priceStaticDayDto.setPriceDatetime(DateUtil.getNewFormatDateString(priceStaticDayDto.getPriceDate()));
            return priceStaticDayDto;
        }).collect(Collectors.toList())).orElse(null);
        QueryResult<PriceStaticDayDto> priceStaticDayDtoQueryResult=new QueryResult<>();
        priceStaticDayDtoQueryResult.setResultlist(priceStaticDayDtoList);
        priceStaticDayDtoQueryResult.setCurrentPage(priceStaticMapperQueryResult.getCurrentPage());
        priceStaticDayDtoQueryResult.setTotalrecord(priceStaticMapperQueryResult.getTotalrecord());
        return priceStaticDayDtoQueryResult;
    }


    @Override
    public void deletePriceStaticDay(PriceStaticBaseParamDto priceStaticBaseParamDto) throws Exception {
        commonService.delete(PriceStaticDay.class, priceStaticBaseParamDto.getId());
    }

    /**
     * 批量删除特定日期价格设置
     * @param priceStaticBaseParamDto
     * @throws Exception
     */
    @Override
    public void deletePriceStaticDayBatch(PriceStaticBaseParamDto priceStaticBaseParamDto)throws Exception{
        if(priceStaticBaseParamDto.getDelPriceStaticDayIds()!=null){
            commonService.delete(PriceStaticDay.class, priceStaticBaseParamDto.getDelPriceStaticDayIds().toArray());
        }
    }

    /**
     * 根据房型启用/停用基价
     * @param priceStaticBaseParamDto
     * @throws Exception
     */
    @Override
    public void updateStaticPrice(PriceStaticBaseParamDto priceStaticBaseParamDto)throws Exception{
        PriceStatic queryStatic=new PriceStatic();
        queryStatic.setLhotelGroupCode(priceStaticBaseParamDto.getLhotelGroupCode());
        queryStatic.setLhotelCode(priceStaticBaseParamDto.getLhotelCode());
        queryStatic.setRmtype(priceStaticBaseParamDto.getRmtype());
        QueryResult<PriceStatic> staticPriceResult = commonService.findAllEQ(PriceStatic.class, queryStatic);
        if(staticPriceResult.getResultlist()!=null){
            for(PriceStatic staticPrice:staticPriceResult.getResultlist()){
                staticPrice.setIsHalt(priceStaticBaseParamDto.getIsHalt());
            }
        }
        commonService.mergeList(staticPriceResult.getResultlist());
    }

    /**
     * 增量更新每日房价
     * @param priceStaticBaseParamDto
     * @throws Exception
     */
    @Override
    public void updateStaticDayPriceIncrement(PriceStaticBaseParamDto priceStaticBaseParamDto)throws Exception{
        String lhotelGroupCode=priceStaticBaseParamDto.getLhotelGroupCode();
        String lhotelCode=priceStaticBaseParamDto.getLhotelCode();
        String rmtype=priceStaticBaseParamDto.getRmtype();
        String priceCode=priceStaticBaseParamDto.getPriceCode();
        Date startDate=priceStaticBaseParamDto.getStartDate();
        Date endDate=priceStaticBaseParamDto.getEndDate();
        L2RAssert.stringBlank(lhotelCode,"lhotelCode is null");
        L2RAssert.stringBlank(rmtype,"rmtype is null");
        L2RAssert.stringBlank(priceCode,"priceCode is null");
        L2RCondition l2RCondition=new L2RCondition();
        l2RCondition.setAndConditions(new ConditionDetail[]{
                new ConditionDetail(BaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ,lhotelGroupCode),
                new ConditionDetail(BaseEntity.BaseEntity_.lhotelCode.toString(), CriteriaUtil.Operator.EQ,lhotelCode),
                new ConditionDetail(PriceStaticDay.PriceStaticDay_.rmtype.toString(), CriteriaUtil.Operator.EQ,rmtype),
                new ConditionDetail(PriceStaticDay.PriceStaticDay_.priceCode.toString(), CriteriaUtil.Operator.EQ,priceCode),
                new ConditionDetail(PriceStaticDay.PriceStaticDay_.priceDate.toString(), CriteriaUtil.Operator.GTE,startDate),
                new ConditionDetail(PriceStaticDay.PriceStaticDay_.priceDate.toString(), CriteriaUtil.Operator.LTE,endDate)
        });
        QueryResult<PriceStaticDay> dayPriceResult = commonService.findAllByCondition(PriceStaticDay.class, l2RCondition);
        List<PriceStaticDay> newDayPriceList = priceStaticBaseParamDto.getDayPrices().stream().map(dayPriceDto ->
                Optional.ofNullable(dayPriceResult.getResultlist()).map(list -> list.stream().filter(dayPrice -> dayPrice.getPriceDate().getTime() == dayPriceDto.getPriceDate().getTime()).findAny().map(dayPrice -> {
                            dayPrice.setPrice(dayPriceDto.getPrice());
                            return dayPrice;
                        }).orElse(ClassConverUtil.copyProperties(dayPriceDto, PriceStaticDay.class))
                ).get()
        ).collect(Collectors.toList());
        commonService.saveOrUpdateList(newDayPriceList);
    }
}
